#include "CP_Dialogs.h"
#include "string.h"

OpenFileOptions make_open_options()
{
    OpenFileOptions o;
    memset(&o, 0, sizeof(o));
    
    o.title = "Open File";
    o.choose_files = 1;
    
    return o;
}

SaveFileOptions make_save_options()
{
    SaveFileOptions o;
    memset(&o, 0, sizeof(o));
    
    o.title = "Open File";
    
    return o;
}

ColorPickerOptions make_color_picker_options()
{
    ColorPickerOptions o;
    memset(&o, 0, sizeof(o));
    
    o.use_alpha = 1;
    
    return o;
}

#ifndef __APPLE__

#ifdef WIN32
#include <windows.h>

#ifndef OFN_FORCESHOWHIDDEN
    #define OFN_FORCESHOWHIDDEN 0x10000000
#endif

#include <stdio.h>

// snprintf workaround from http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
#ifdef _MSC_VER

#define snprintf c99_snprintf

inline int c99_snprintf(char* str, size_t size, const char* format, ...)
{
    int count;
    va_list ap;

    va_start(ap, format);
    count = c99_vsnprintf(str, size, format, ap);
    va_end(ap);

    return count;
}

inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
{
    int count = -1;

    if (size != 0)
        count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
    if (count == -1)
        count = _vscprintf(format, ap);

    return count;
}

#endif // _MSC_VER

#endif

int open_file_dialog(char* result, int result_size, OpenFileOptions* options)
{
    OpenFileOptions o;
    if(options != NULL)
        o = *options;
    else
        o = make_open_options();
    
    
    #ifdef WIN32

    {
        OPENFILENAME ofn;
        char buffer[512];
        const char* filter_string = "All Files\0*.*\0\0";
        char* default_ext = NULL;
        char must_exist = 0;
        
        if(o.filter_string_WIN != NULL)
            filter_string = o.filter_string_WIN;
        
        memset(&ofn, 0, sizeof(OPENFILENAME));
        buffer[0] = '\0';
        if(o.init_file != NULL)
        {
            strncpy(buffer, o.init_file, 511);
            buffer[511] = '\0';
        }

        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = NULL;
        ofn.lpstrTitle = o.title;
        ofn.lpstrFile = buffer;
        ofn.nMaxFile = sizeof(buffer);
        ofn.lpstrFilter = filter_string;
        ofn.nFilterIndex = 1;
        ofn.lpstrFileTitle = NULL;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.lpstrDefExt = default_ext;
        ofn.Flags = 0;
        if(must_exist)
            ofn.Flags |= (OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST);
        if(o.show_hidden)
            ofn.Flags |= OFN_FORCESHOWHIDDEN;

        if(GetOpenFileName(&ofn) != 0)
        {
            strncpy(result, buffer, result_size-1);
            result[result_size-1] = '\0';
            return 1;
        }
    }
    #endif // WIN32
    
    return 0;
}

int open_files_dialog(char** result, int max_results, int result_size, OpenFileOptions* options)
{
    OpenFileOptions o;
    if(options != NULL)
        o = *options;
    else
        o = make_open_options();
    
    
    #ifdef WIN32

    {
        OPENFILENAME ofn;
        char buffer[1024];
        const char* filter_string = "All Files\0*.*\0\0";
        char* default_ext = NULL;
        char must_exist = 0;
        
        if(o.filter_string_WIN != NULL)
            filter_string = o.filter_string_WIN;
        
        memset(&ofn, 0, sizeof(OPENFILENAME));
        buffer[0] = '\0';
        if(o.init_file != NULL)
        {
            strncpy(buffer, o.init_file, 1023);
            buffer[1023] = '\0';
        }

        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = NULL;
        ofn.lpstrTitle = o.title;
        ofn.lpstrFile = buffer;
        ofn.nMaxFile = sizeof(buffer);
        ofn.lpstrFilter = filter_string;
        ofn.nFilterIndex = 1;
        ofn.lpstrFileTitle = NULL;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.lpstrDefExt = default_ext;
        ofn.Flags = 0;
        ofn.Flags |= OFN_ALLOWMULTISELECT | OFN_EXPLORER;
        if(must_exist)
            ofn.Flags |= (OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST);
        if(o.show_hidden)
            ofn.Flags |= OFN_FORCESHOWHIDDEN;

        if(GetOpenFileName(&ofn) != 0)
        {
            int i;
            char directory[1024];
            char* current_string = buffer;
            
            // Get the directory
            strncpy(directory, buffer, 1024);
            
            for(i = 0; i < max_results && current_string != '\0'; i++)
            {
                // Skip to next file
                while(*current_string != '\0')
                    current_string++;
                current_string++;
                
                if(strcmp(current_string, "") == 0)
                {
                    // Only 1 file?
                    if(i == 0)
                    {
                        snprintf(result[i], result_size-1, "%s", directory);
                        result[i][result_size-1] = '\0';
                        return 1;
                    }
                    break;
                }
                
                snprintf(result[i], result_size-1, "%s\\%s", directory, current_string);
                result[i][result_size-1] = '\0';
                
            }
            return i;
        }
    }
    #endif // WIN32
    
    return 0;
}

int save_file_dialog(char* result, int result_size, SaveFileOptions* options)
{
    SaveFileOptions o;
    if(options != NULL)
        o = *options;
    else
        o = make_save_options();
    
    
    #ifdef WIN32

    {
        OPENFILENAME ofn;
        char buffer[512];
        const char* filter_string = "All Files\0*.*\0\0";
        char* default_ext = NULL;
        char must_exist = 0;
        
        if(o.filter_string_WIN != NULL)
            filter_string = o.filter_string_WIN;
        
        memset(&ofn, 0, sizeof(OPENFILENAME));
        buffer[0] = '\0';
        if(o.init_file != NULL)
        {
            strncpy(buffer, o.init_file, 511);
            buffer[511] = '\0';
        }

        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = NULL;
        ofn.lpstrTitle = o.title;
        ofn.lpstrFile = buffer;
        ofn.nMaxFile = sizeof(buffer);
        ofn.lpstrFilter = filter_string;
        ofn.nFilterIndex = 1;
        ofn.lpstrFileTitle = NULL;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.lpstrDefExt = default_ext;
        ofn.Flags = 0;
        ofn.Flags |= OFN_OVERWRITEPROMPT;
        if(must_exist)
            ofn.Flags |= (OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST);
        if(o.show_hidden)
            ofn.Flags |= OFN_FORCESHOWHIDDEN;

        if(GetSaveFileName(&ofn) != 0)
        {
            strncpy(result, buffer, result_size-1);
            result[result_size-1] = '\0';
            return 1;
        }
    }
    #endif // WIN32
    
    return 0;
}

int color_picker_dialog(int* r, int* g, int* b, int* a, ColorPickerOptions* options)
{
    ColorPickerOptions o;
    if(options != NULL)
        o = *options;
    else
        o = make_color_picker_options();
    
    #ifdef WIN32

    {
        static COLORREF acrCustClr[16]; // array of custom colors
        static char first = 1;
        int i;
        CHOOSECOLOR cc;
        
        memset(&cc, 0, sizeof(CHOOSECOLOR));



        if(first)
        {
            first = 0;
            for(i = 0; i < 16; i++)
                acrCustClr[i] = RGB(255, 255, 255);
        }

        cc.lStructSize = sizeof(CHOOSECOLOR);
        cc.lpCustColors = (LPDWORD)acrCustClr;
        cc.Flags = CC_FULLOPEN;

        if(ChooseColor(&cc) != 0)
        {
            if(r != NULL)
                *r = GetRValue(cc.rgbResult);
            if(g != NULL)
                *g = GetGValue(cc.rgbResult);
            if(b != NULL)
                *b = GetBValue(cc.rgbResult);
            if(a != NULL)
                *a = 255;
            return 1;
        }
    }
    #endif // WIN32

    return 0;
}

#endif



